// 神秘商店
package m

import (
	"GameServer/Common/utils"
	"time"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Common/data"
	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
)

type HideShopGoods struct {
	Id    int64  `bson:"id"`
	Num   int64  `bson:"num"`
	Goods *Goods `bson:"goods"`
}

type HideShop struct {
	BaseM
	Uid         bson.ObjectId            `bson:"_id" json:"_id"`
	EndTime     int64                    `bson:"endTime" json:"endTime"`         // 结束时间
	NextTime    int64                    `bson:"nextTime" json:"nextTime"`       // 下次可刷新时间
	FireNum     int64                    `bson:"fireNum" json:"fireNum"`         // 交互次数
	FreshNum    int64                    `bson:"freshNum" json:"freshNum"`       // 刷新次数
	AutoReFresh bool                     `bson:"autoReFresh" json:"autoReFresh"` // 自动刷新
	Goods       map[int64]*HideShopGoods `bson:"goods" json:"goods"`             // 物品
	AdGoods     map[int64]*HideShopGoods `bson:"adGoods" json:"adGoods"`         // 广告物品
	LastTime    int64                    `bson:"lastTime" json:"lastTime"`       // 上次激活时间
	IsSpecial   int64                    `bson:"isSpecial" json:"isSpecial"`     // 0-正常时间启动的商店 1-Gm指令或交互15次获得
}

func NewHideShop() cache.EntryI {
	return &HideShop{
		Goods:   make(map[int64]*HideShopGoods),
		AdGoods: make(map[int64]*HideShopGoods),
	}
}

// 保存信息
func (hs *HideShop) Save() (err error) {
	mdata := make(map[string]interface{}, 0)
	mdata["_id"] = hs.Uid
	mdata["endTime"] = hs.EndTime
	mdata["nextTime"] = hs.NextTime
	mdata["fireNum"] = hs.FireNum
	mdata["freshNum"] = hs.FreshNum
	mdata["autoReFresh"] = hs.AutoReFresh
	mdata["lastTime"] = hs.LastTime
	mdata["isSpecial"] = hs.IsSpecial

	if hs.Goods != nil && len(hs.Goods) > 0 {
		mdata["goods"] = hs.Goods
	}

	if hs.AdGoods != nil && len(hs.AdGoods) > 0 {
		mdata["adGoods"] = hs.AdGoods
	}

	err = dbmodule.MgoDB.GameDB.Upsert("hideShop", bson.M{"_id": hs.Uid}, mdata)
	if err != nil {
		return err
	}
	return
}

func (hs *HideShop) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		hs.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		hs.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "HideShop_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return hs.LoadData()
}

// 加载数据
func (hs *HideShop) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("hideShop", bson.M{"_id": hs.Uid}, nil, &hs)
	if err != nil {
		if err.Error() == "not found" {
			err = hs.InitHideShop()
			if err != nil {
				return err
			}
			return nil
		}
		return
	}
	if hs.Goods == nil {
		hs.Goods = make(map[int64]*HideShopGoods, 0)
	}
	if hs.AdGoods == nil {
		hs.AdGoods = make(map[int64]*HideShopGoods, 0)
	}
	return
}

// 更新数据
func (hs *HideShop) Update(val *HideShop) {
	Cache.Put("hideShop", hs.Uid.Hex(), val)
	val.UpdateData()
}

func (hs *HideShop) InitHideShop() (err error) {
	now := utils.TNow()
	if hs.EndTime < now.Unix() {
		hs.FireNum = 0
		hs.FreshNum = 0
		hs.NextTime = 0
		hs.LastTime = 0
		hs.IsSpecial = 0
		hs.Goods = make(map[int64]*HideShopGoods, 0)
		hs.AdGoods = make(map[int64]*HideShopGoods, 0)
	}
	nextTime, err := hs.ReFreshNextTime(now.Unix())
	if err != nil {
		return
	}
	hs.NextTime = nextTime
	hs.Update(hs)
	return
}

func (hs *HideShop) AddFireNum(slotKey int64) (realFireNum int64) {
	nowTime := utils.TNow().Unix()
	realFireNum = hs.FireNum
	if nowTime < hs.EndTime {
		// 结束时间内，不累加交互次数
		return realFireNum
	} else {
		if slotKey == 555 || slotKey == 666 {
			hs.FireNum += 1
			realFireNum = hs.FireNum
			hs.Update(hs)
		}
	}
	return realFireNum
}

func (hs *HideShop) SetFireNum(targetFireNum int64) {
	hs.FireNum = targetFireNum
	hs.Update(hs)
}

func (hs *HideShop) GetHideShopGoods(id int64) (r *HideShopGoods, ok bool) {
	r, ok = hs.Goods[id]
	return
}

func (hs *HideShop) GetHideShopAdGoods(id int64) (r *HideShopGoods, ok bool) {
	r, ok = hs.AdGoods[id]
	return
}

func (u *User) HideShop() *HideShop {
	v, _ := Cache.Get("hideShop", u.Uid.Hex())
	return v.(*HideShop)
}

func (u *User) UpdateHideShop(hs *HideShop) {
	//defer hs.UpdateData()
	Cache.Put("hideShop", u.Uid.Hex(), hs)
	hs.UpdateData()
}

func (hs *HideShop) ReFreshNextTime(nextTime int64) (r int64, err error) {
	nextT := utils.TTime(nextTime, 0)
	list, ok := data.GetAllDatas("HideShopRefreshTimes")
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, "没有神秘商店刷新时间配置")
		return
	}

	checkIsNoRefreshTime := func(t time.Time) bool {
		for _, item := range list {
			itemv := item.(data.HideShopRefreshTime)
			beginTime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.NoRefreshTime.BeginHour), int(itemv.NoRefreshTime.BeginMinute), 0, 0, t.Location())
			endTime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.NoRefreshTime.EndHour), int(itemv.NoRefreshTime.EndMinute), 0, 0, t.Location())
			if t.Unix() >= beginTime.Unix() && t.Unix() <= endTime.Unix() {
				return true
			}
		}
		return false
	}

	refreshTime := func(t time.Time) int64 {
		var findNextTime bool = false
		for _, item := range list {
			itemv := item.(data.HideShopRefreshTime)
			rtime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.RefreshTime.HourTime), int(itemv.RefreshTime.Minute), 0, 0, t.Location())
			if rtime.Unix() >= t.Unix() {
				findNextTime = true
				return rtime.Unix()
			}
		}
		//当天时间找不到，往后推一天，寻找下一个刷新时间
		if findNextTime == false {
			NewT := t.AddDate(0, 0, 1)
			for _, item := range list {
				itemv := item.(data.HideShopRefreshTime)
				rtime := time.Date(NewT.Year(), NewT.Month(), NewT.Day(), int(itemv.RefreshTime.HourTime), int(itemv.RefreshTime.Minute), 0, 0, NewT.Location())
				if rtime.Unix() >= t.Unix() {
					return rtime.Unix()
				}
			}
		}
		return 0
	}
	defer hs.Update(hs)
	if checkIsNoRefreshTime(nextT) {
		r = refreshTime(nextT)
		hs.AutoReFresh = true
		return
	}
	hs.AutoReFresh = false
	r = refreshTime(nextT)
	return
}

//检查是否在刷新时间内，返回当前时间匹配的时间段，并且更新玩家的，EndTime到下次的结束时间，或者本次的结束时间，NextTime到下次刷新时间
func (hs *HideShop) CheckInHideShopTime(nowTime int64) (inTime bool, curBeginTime int64, curEndTime int64, curNextTime int64, err error) {
	nowT := utils.TTime(nowTime, 0)
	curBeginTime = 0
	curEndTime = 0
	curNextTime = 0
	list, ok := data.GetAllDatas("HideShopRefreshTimes")
	if !ok {
		inTime = false
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, "没有神秘商店刷新时间配置")
		return
	}
	//Func 检查是否在不可刷新时间内
	checkIsNoRefreshTime := func(t time.Time) bool {
		for _, item := range list {
			itemv := item.(data.HideShopRefreshTime)
			beginTime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.NoRefreshTime.BeginHour), int(itemv.NoRefreshTime.BeginMinute), 0, 0, t.Location())
			endTime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.NoRefreshTime.EndHour), int(itemv.NoRefreshTime.EndMinute), 0, 0, t.Location())
			if t.Unix() >= beginTime.Unix() && t.Unix() <= endTime.Unix() {
				return true
			}
		}
		return false
	}
	//Func 寻找当前匹配的时间段，返回匹配的开始时间和结束时间
	checkIsRefreshTime := func(t time.Time) (find bool, checkBeginTime int64, checkEndTime int64) {
		find = false
		checkBeginTime = 0
		checkEndTime = 0
		for _, item := range list {
			itemv := item.(data.HideShopRefreshTime)
			beginTime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.RefreshTime.HourTime), int(itemv.RefreshTime.Minute), 0, 0, t.Location())
			endTime := beginTime.Add(time.Duration(data.HideShopEnum.LifeTime) * time.Second)
			if t.Unix() >= beginTime.Unix() && t.Unix() <= endTime.Unix() {
				find = true
				checkBeginTime = beginTime.Unix()
				checkEndTime = endTime.Unix()
			}
		}
		//当天时间找不到，往后推一天，寻找下一个刷新时间
		if find == false {
			NewT := t.AddDate(0, 0, 1)
			for _, item := range list {
				itemv := item.(data.HideShopRefreshTime)
				beginTime := time.Date(NewT.Year(), NewT.Month(), NewT.Day(), int(itemv.RefreshTime.HourTime), int(itemv.RefreshTime.Minute), 0, 0, NewT.Location())
				endTime := beginTime.Add(time.Duration(data.HideShopEnum.LifeTime) * time.Second)
				if t.Unix() >= beginTime.Unix() && t.Unix() <= endTime.Unix() {
					find = true
					checkBeginTime = beginTime.Unix()
					checkEndTime = beginTime.Unix() + data.HideShopEnum.LifeTime
				}
			}
		}
		return find, checkBeginTime, checkEndTime
	}
	//Func 寻找下一个刷新时间
	findNextFreshTime := func(t time.Time) int64 {
		var findNextTime bool = false
		for _, item := range list {
			itemv := item.(data.HideShopRefreshTime)
			rtime := time.Date(t.Year(), t.Month(), t.Day(), int(itemv.RefreshTime.HourTime), int(itemv.RefreshTime.Minute), 0, 0, t.Location())
			if rtime.Unix() >= t.Unix() {
				findNextTime = true
				return rtime.Unix()
			}
		}
		//当天时间找不到，往后推一天，寻找下一个刷新时间
		if findNextTime == false {
			NewT := t.AddDate(0, 0, 1)
			for _, item := range list {
				itemv := item.(data.HideShopRefreshTime)
				rtime := time.Date(NewT.Year(), NewT.Month(), NewT.Day(), int(itemv.RefreshTime.HourTime), int(itemv.RefreshTime.Minute), 0, 0, NewT.Location())
				if rtime.Unix() >= t.Unix() {
					return rtime.Unix()
				}
			}
		}
		return 0
	}

	defer hs.Update(hs)
	isNoRefreshTime := checkIsNoRefreshTime(nowT)
	isRefreshTime, newBeginTime, newEndTime := checkIsRefreshTime(nowT)
	newNextTime := findNextFreshTime(nowT)
	curBeginTime = newBeginTime
	curEndTime = newEndTime
	curNextTime = newNextTime
	// hs.EndTime = newEndTime
	hs.NextTime = newNextTime
	if isNoRefreshTime {
		inTime = false
		return
	}
	if isRefreshTime {
		inTime = true
	}
	return
}
